
/*
 * Copyright (C) 2010 Bitglue. All rights reserved.
 *
 * $Id: LoginController.java bself $
 */

package com.bitglue.web.admin.webmvc;

import com.bitglue.hibernate.dao.AdminUserDAO;
import com.bitglue.hibernate.model.AdminUser;
import com.bitglue.web.admin.webmvc.model.LoginModel;

import java.util.Date;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.log4j.Logger;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.SessionAttributes;
import org.springframework.web.bind.support.SessionStatus;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.util.WebUtils;

/**
 * LoginController checks admin console login credentials.
 * @author Bryan Patrick Self
 */
@Transactional
@Controller("loginController")
@SessionAttributes(types = LoginModel.class)
public class LoginController {

    private static final String LOGIN_FAILED = "login.failure";

    protected final Logger log = Logger.getLogger(getClass());

    @Autowired
    protected AdminUserDAO adminUserDAO;

    @RequestMapping(value = "/login.do", method = RequestMethod.GET)
    public ModelAndView loginSetup(HttpServletRequest req) {
        log.debug("creating new login model for client "
          + req.getRemoteAddr());
        LoginModel loginModel = new LoginModel();
        return new ModelAndView("login", "loginModel", loginModel);
    }

    @RequestMapping(value = "/login.do", method = RequestMethod.POST)
    public String login(@ModelAttribute LoginModel loginModel,
      BindingResult result, SessionStatus status,
      HttpServletRequest req, HttpServletResponse resp) {
        log.debug("starting authentication process for " + req.getRemoteAddr());
        String name = loginModel.getUsername();
        try {
            AdminUser user = adminUserDAO.getAdminUserByName(name);
            if (user == null)
                throw new Exception("no such user " + name + " exists");
            String pwd = AdminUser.md5hash(loginModel.getPassword());
            if (!user.getPasswordHash().equals(pwd))
                throw new Exception("password mismatch for " + name);
            log.debug("setting admin user '" + name + "' in session");
            WebUtils.setSessionAttribute(req, "user", user);
            updateTimestamp(user);

        } catch (Exception ex) {
            log.debug("login failed for " + name + ": " + ex);
            result.rejectValue("username", LOGIN_FAILED, LOGIN_FAILED);
            return "login";
        }
        status.setComplete();
        return "redirect:/console.do";
    }

    @Transactional
    public void updateTimestamp(AdminUser user) {
        Date date = new Date();
        log.debug("updating user timestamp for "
          + user.getUsername() + " to " + date);
        user.setTimeLastLogin(date);
        adminUserDAO.storeAdminUser(user);
    }

}
